/*
1.PBR是基于物理渲染的着色模型，PBR着色模型分为材质和灯光两个属性
2.材质部分由：基础色，法线，高光，粗糙度，金属度来定义材质表面属性的
3.灯光部分是由：直接照明，间接照明，直接高光，间接高光，阴影，环境光闭塞来定义照明属性的
4.通常我们写材质的时候只需要关注材质部分的属性即可，灯光属性都是引擎定义好的直接用的即可
5.PBR渲染模型不但指的是PBR材质，还有灯光，两者缺一不可


标准网络材质与光照物理效果

MeshStandardMaterial标准网格材质

环境光
THREE.AmbientLight

直线光源
THREE.DirectionalLight

置换贴图  displacementMap
最长5公分 displacementScale: 0.05 
物体顶点数量需要设置高点才明显（顶点细分）
new THREE.BoxGeometry(1,1,1, 100, 100, 100);

整个物体粗糙程度设置 roughness
粗糙贴图 roughnessMap
两个粗糙程度可以相乘

金属度 metalness
metalness: 1,
metalnessMap
可以相乘

法线贴图   反射光效果
normalMap

材质纹理素材
poliigon.com
arroway-textures.ch

纹理加载进度情况
封装纹理加载器统一处理
  let event = {}
  //单张纹理图的加载进度
  event.onLoad = ()=>{
    console.log('图片加载完成')
  }
  event.onProgress = (url, num, total)=>{
    console.log('图片加载完成',url)
    console.log('图片加载进度',num)
    console.log('图片总数',total)
    console.log('图片加载百分比：', ((num / total) * 100).toFixed(2)) + '%'
  }
  event.onError = (e)=>{
    console.log('图片加载错误',e)
  }

  //设置加载管理器
  const LoadingManager = new THREE.LoadingManager(
    event.onLoad,
    event.onProgress,
    event.onError
  )
  //导入纹理
  const textureLoader = new THREE.TextureLoader(LoadingManager)

环境纹理贴图


*/


import *  as THREE from 'three'
import { AxesHelper } from 'three';
import gsap from 'gsap'
import * as dat from 'dat.gui'

//导入轨道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'

//1.创建场景
const scene = new THREE.Scene()

//2.创建相机 (透视相机)
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

//设置相机位置
camera.position.set(0, 0, 5);
scene.add(camera);

//导入纹理
const textureLoader = new THREE.TextureLoader()
const doorColorTexture = textureLoader.load('./textures/door/color.png')


const doorAplhaTexture = textureLoader.load('./textures/door/alpha.jpeg')
const doorAoTexture = textureLoader.load('./textures/door/ambientOcclusion.jpeg')
//导入置换贴图
const doorHeightTexture = textureLoader.load('./textures/door/height.jpeg')

// doorColorTexture.offset.x = 0.5;
// doorColorTexture.offset.y = 0.5;
// doorColorTexture.offset.set(0.5, 0.5);
// doorColorTexture.rotation = Math.PI;
// doorColorTexture.center.set(0.5, 0.5);
// doorColorTexture.repeat.set(2, 3);
// doorColorTexture.wrapS = THREE.MirroredRepeatWrapping;
// doorColorTexture.wrapT = THREE.RepeatWrapping;

// doorColorTexture.minFilter = THREE.NearestFilter;
// doorColorTexture.magFilter = THREE.NearestFilter;
// doorColorTexture.minFilter = THREE.LinearFilter;
// doorColorTexture.magFilter = THREE.LinearFilter;

//添加物体
const cubeGeometry = new THREE.BoxGeometry(1,1,1, 100, 100, 100);
//材质
const basicMaterial = new THREE.MeshStandardMaterial({
  color: "#ffff00",
  map: doorColorTexture,
  alphaMap: doorAplhaTexture, 
  transparent: true,
  side: THREE.DoubleSide,
  aoMap: doorAoTexture, //需要第二组uv
  aoMapIntensity: 0.5,
  displacementMap: doorHeightTexture,
  displacementScale: 0.05
})
const cube = new THREE.Mesh(cubeGeometry, basicMaterial);
scene.add(cube);
cubeGeometry.setAttribute(
  "uv2",
  new THREE.BufferAttribute(cubeGeometry.attributes.uv.array, 2)
)

//灯光
//环境光
const light = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(light)

//直线光源
const directionLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionLight.position.set(10, 10, 10)
scene.add(directionLight);


//添加平面
const planeGeometry  = new THREE.PlaneGeometry(1, 1, 200, 200);
const plane = new THREE.Mesh(
  planeGeometry,
  basicMaterial
)
plane.position.set(3, 0, 0)

scene.add(plane)
planeGeometry.setAttribute(
  "uv2",
  new THREE.BufferAttribute(planeGeometry.attributes.uv.array, 2)
)

//初始化渲染器
const renderer = new THREE.WebGLRenderer();
//设置渲染器大小
renderer.setSize(window.innerWidth, window.innerHeight);

//将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement)

//使用渲染器，通过相机将场景渲染进来
renderer.render(scene, camera);

//添加坐标辅助器
const axesHelper = new AxesHelper(5)
scene.add(axesHelper)
//创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;

const clock=new THREE.Clock()

function render(){
  controls.update()
  //获取时钟运行的总时长
  let time = clock.getElapsedTime();
  renderer.render(scene,camera)
  //调用下一帧的时候就会调用render渲染
  requestAnimationFrame(render)
}

render();